#include "protocol.h"
#include "main.h"
#include "logger.h"
#include "tlv.h"


void readAsciiz(char *dst, guchar ** buf, int max_len)
{
    guint16  len;

    unpackLEWord( buf, &len );

    if ( dst ) {
        if( dst && len ) {
            strncpy( dst, (char*)*buf, MIN(len, max_len) );
        } else
            memset( dst, 0, max_len );
    }

    *buf += len;
}

int fam_extensions( CLIENT * c, flap_pk_t * pk, guint16 sub, guint16 flags, guint32 req_id, guchar * buf, guint16 size )
{
    //BYTE *		end = buf + size;

    g_debug( "size = %d", size );

        switch (sub) {

        case ICQ_META_ERROR:
                //handleExtensionError(buf, wLen);
                break;

        case ICQ_META_SRV_REPLY:
                //handleExtensionServerInfo(c, buf, size, flags);
                guint16 type;

                unpackWord(&buf, NULL); //word	 	    TLV.Type(1) - encapsulated META_DATA
                unpackWord(&buf, NULL); //word	 	    TLV.Length

                unpackLEWord(&buf, NULL); //word (LE)	data chunk size (TLV.Length-2)
                unpackLEDWord(&buf, NULL);//dword (LE)	request owner uin
                unpackLEWord(&buf, NULL); //word (LE)	data type: META_DATA
                unpackLEWord(&buf, NULL); //word (LE)	request sequence number
                unpackLEWord(&buf, &type);// data subtype

                unpackByte(&buf, NULL); // success byte

                //while ( buf < end ) {

                    switch (type) {

                        case META_BASIC_USERINFO: //  basic user information
                            {
                                readAsciiz( c->vcard.nick         , &buf, 32); // nickname
                                readAsciiz( c->vcard.first_name   , &buf, 32); // first name
                                readAsciiz( c->vcard.last_name    , &buf, 32); // last name
                                readAsciiz( c->vcard.email        , &buf, 32); // email
                                readAsciiz( c->vcard.home_city    , &buf, 32); // home city
                                readAsciiz( c->vcard.home_state   , &buf, 32); // home state
                                readAsciiz( c->vcard.home_phones  , &buf, 32); // home phone
                                readAsciiz( c->vcard.home_fax     , &buf, 32); // home fax
                                readAsciiz( c->vcard.home_address , &buf, 256);// home address
                                readAsciiz( c->vcard.cell_phone   , &buf, 32); // cell phone

                                /*readAsciiz( NULL               , &buf, 0);  // home zip code
                                unpackLEWord(&buf, NULL);                   // home country code

                                guchar gmt_offset;
                                guchar auth_flag;
                                guchar webaware_flag;
                                guchar direct_connection_permissions;
                                guchar publish_primary_email_flag;

                                unpackByte(&buf, &gmt_offset);
                                unpackByte(&buf, &auth_flag);
                                unpackByte(&buf, &webaware_flag);
                                unpackByte(&buf, &direct_connection_permissions);
                                unpackByte(&buf, &publish_primary_email_flag);*/
                                c->prot->packet_counter++;
                                break;
                            }

                        case 0x00DC: // more user information
                            {
                                unpackLEWord(&buf, NULL); // age
                                unpackByte(&buf, (guchar*)&c->vcard.gender);

                                readAsciiz( c->vcard.home_page    , &buf, 128); // home page

                                guint16 year;
                                guchar mon;
                                guchar day;

                                unpackLEWord(&buf, &year);
                                unpackByte(&buf, &mon);
                                unpackByte(&buf, &day);

                                if (year != 0)
                                    sprintf( c->vcard.birthday, "%d.%d.%d", day, mon, year );
                                else
                                    sprintf( c->vcard.birthday, "%d.%d", day, mon );

                                unpackByte(&buf, NULL); // speaking language 1
                                unpackByte(&buf, NULL); // speaking language 2
                                unpackByte(&buf, NULL); // speaking language 3

                                //unpackLEWord(&buf, NULL);

                                readAsciiz(NULL, &buf, 0); // original from: city
                                readAsciiz(NULL, &buf, 0); // original from: state

                                unpackLEWord(&buf, NULL);  // original from: country code
                                unpackByte(&buf, NULL);    // user TimeZone
                                c->prot->packet_counter++;
                                break;
                            }

                        case 0x00D2: // work user information
                            {
                                readAsciiz( c->vcard.work_city    , &buf, 32);
                                readAsciiz( c->vcard.work_state   , &buf, 32);
                                readAsciiz( c->vcard.work_phone   , &buf, 32);
                                readAsciiz( c->vcard.work_fax     , &buf, 32);
                                readAsciiz( c->vcard.work_address , &buf, 32);

                                readAsciiz( NULL, &buf, 0 );                  // work zip code
                                unpackLEWord(&buf, NULL);                     // work country code
                                readAsciiz( c->vcard.work_company   , &buf, 32); // work company
                                readAsciiz( c->vcard.work_department, &buf, 32); // work department
                                readAsciiz( c->vcard.work_position  , &buf, 32); // work position

                                unpackLEWord(&buf, NULL);                     // work ocupation

                                readAsciiz( c->vcard.work_webpage  , &buf, 128); // work webpage
                                c->prot->packet_counter++;
                                break;
                            }

                        case 0x00E6: // user about information
                            {
                                readAsciiz( c->vcard.about, &buf, 512);
                                c->prot->packet_counter++;
                                break;
                            }

                        case 0x00F0: // user interests information
                            {
                                gchar   str[512];
                                guchar  counter;
                                unpackByte(&buf, &counter);

                                for (int i = 0; i < counter; ++i) {
                                    unpackLEWord(&buf, NULL);
                                    readAsciiz( str, &buf, 64);
                                    strcat( c->vcard.interests, str);

                                    if( (i + 1) != counter )
                                        strcat( c->vcard.interests, ", " );
                                }
                                c->prot->packet_counter++;
                                break;
                            }
                    //}
                }

                if( c->prot->packet_counter >= 5 )
                    P_SendVCard( c, &c->vcard, "" );

                break;

        default:
                g_warning("Warning: Ignoring SNAC(0x15,x%02x) - Unknown SNAC (Flags: %u, Ref: %u", sub, flags, req_id);
                break;
        }
    return 0;
}
